package com.jl.registermvc;

import com.jl.resolver.ContractRequestBodyArgumentResolver;
import com.jl.util.ClassUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import java.util.List;

public class ContractReturnValueWebMvcConfigurer implements BeanFactoryAware, InitializingBean {

    private WebMvcConfigurationSupport webMvcConfigurationSupport;

    private ConfigurableBeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        if (beanFactory instanceof ConfigurableBeanFactory) {
            this.beanFactory = (ConfigurableBeanFactory) beanFactory;
            this.webMvcConfigurationSupport = beanFactory.getBean(WebMvcConfigurationSupport.class);
        }
    }

    @Override
    public void afterPropertiesSet() {
        if (this.beanFactory == null) {
            throw new IllegalStateException("beanFactory cannot use");
        }
        if (this.webMvcConfigurationSupport == null) {
            throw new IllegalStateException("webMvcConfigurationSupport cannot use");
        }
        try {
            Class<WebMvcConfigurationSupport> configurationSupportClass = WebMvcConfigurationSupport.class;
            List<HandlerMethodArgumentResolver> argumentResolverHandlers = ClassUtil.invokeNoParameterMethod(configurationSupportClass, webMvcConfigurationSupport, "getArgumentResolvers");
            argumentResolverHandlers.add(new ContractRequestBodyArgumentResolver());
        } catch (Exception e) {
            throw new IllegalStateException("Annotation ArgumentResolver add fail");
        }

        //通过反射调用WebMvcConfigurationSupport方法的操作不用担心会消失，因为这几个接口都是 protected 的，所以他们是作为扩展接口来提供的
    }
}
